package bigbeard.tools.thread.pools;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author by bigbeard on 2018/9/14.
 * <p>
 * 线程构造信息
 */
public class ThreadFactoryBuilder {


    private String namePrefix = null;
    private boolean daemon = false;
    private int priority = Thread.NORM_PRIORITY;

    private UncaughtExceptionHandler uncaughtExceptionHandler = null;
    private ThreadFactory backingThreadFactory = null;

    private static ThreadFactory build(ThreadFactoryBuilder builder) {
        final String namePrefix = builder.namePrefix;
        final boolean daemon = builder.daemon;
        final int priority = builder.priority;

        final String nameFormat = builder.namePrefix;

        final UncaughtExceptionHandler uncaughtExceptionHandler =
                builder.uncaughtExceptionHandler;

        final ThreadFactory backingThreadFactory =
                (builder.backingThreadFactory != null)
                        ? builder.backingThreadFactory
                        : Executors.defaultThreadFactory();

        final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;

        return (Runnable runnable) -> {
            Thread thread = backingThreadFactory.newThread(runnable);
            if (namePrefix != null) {
                thread.setName(format(namePrefix, count.getAndIncrement()));
            }
            thread.setDaemon(daemon);
            thread.setPriority(priority);
            if (null != uncaughtExceptionHandler) {
                thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
            }
            return thread;
        };
    }

    private static String format(String format, Object... args) {
        return String.format(Locale.ROOT, format, args);
    }


    /**
     * 设置线程名称,支持%s等方式进行格式化
     *
     * @param namePrefix 名称
     * @return 当前对象
     */
    public ThreadFactoryBuilder setNamePrefix(String namePrefix) {
        this.namePrefix = namePrefix;
        return this;
    }

    /**
     * 设置线程是否为守护线程
     *
     * @param daemon true:守护线程,否则前台线程
     * @return 当前对象
     */
    public ThreadFactoryBuilder setDaemon(boolean daemon) {
        this.daemon = daemon;
        return this;
    }

    /**
     * 设置线程优先级
     *
     * @param priority 优先级,大于0的整数
     * @return 当前对象
     */
    public ThreadFactoryBuilder setPriority(int priority) {
        if (priority < Thread.MIN_PRIORITY) {
            throw new IllegalArgumentException(String.format(
                    "Thread priority (%s) must be >= %s", priority, Thread.MIN_PRIORITY));
        }

        if (priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(String.format(
                    "Thread priority (%s) must be <= %s", priority, Thread.MAX_PRIORITY));
        }

        this.priority = priority;
        return this;
    }


    /**
     * @param factory 线程构造器
     */
    public ThreadFactoryBuilder setThreadFactory(ThreadFactory factory) {
        this.backingThreadFactory = factory;
        return this;
    }

    /**
     * 设置线程未处理异常的处理接口
     *
     * @param uncaughtExceptionHandler 接收未处理异常的接口
     */
    public ThreadFactoryBuilder setUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler) {
        this.uncaughtExceptionHandler = uncaughtExceptionHandler;
        return this;
    }

    /**
     * 创建构造信息对象
     *
     * @return 构造信息对象
     */
    public ThreadFactory build() {
        return build(this);
    }
}
